/**
 * @file 工具栏按钮辅助工具
 * @description 为渲染进程提供工具栏按钮事件转发机制
 * @author 黄敏
 * @version 1.0.0
 * @since 2025-10-25
 */

import { toolbarTopic } from '~shared/ipc-topic'

/**
 * 带回调函数的按钮配置接口
 */
export interface ButtonConfigWithCallback extends Omit<F2.toolbar.ButtonConfig, 'id'> {
  /** 按钮唯一标识 */
  id?: string
  /** 点击回调函数 */
  onClick: () => void
  /** 为了更好的定位使用data-testid 增加一个属性 */
  attrs?: Record<string, any> // 添加 attrs 属性支持  为了更好的定位使用data-testid
}

/**
 * 工具栏配置（包含回调函数）
 * 继承 F2.toolbar.Config，只覆盖需要支持回调函数的按钮配置字段
 */
export interface ToolbarConfigWithCallback
  extends Omit<F2.toolbar.Config, 'leftBtns' | 'rightBtns'> {
  /** 左侧按钮配置数组（支持回调函数） */
  leftBtns?: ButtonConfigWithCallback[]
  /** 右侧按钮配置数组（支持回调函数） */
  rightBtns?: ButtonConfigWithCallback[]
}

/**
 * 工具栏按钮管理器
 * 用于在 tab 内容页面中注册按钮点击事件监听器
 */
class ToolbarButtonManager {
  private listeners: Map<string, () => void> = new Map()
  private isListening = false
  private cleanupFn: (() => void) | null = null

  /**
   * 开始监听按钮点击事件
   */
  private startListening() {
    if (this.isListening) return

    // 监听来自主进程的按钮点击事件
    const ipcListener = (data: { buttonId: string }) => {
      const { buttonId } = data
      const callback = this.listeners.get(buttonId)
      if (callback) {
        try {
          callback()
        } catch (error) {
          console.error(`[ToolbarHelper] 按钮回调执行失败:`, error)
        }
      }
    }

    // 使用 preload 提供的 IPC 监听，返回清理函数
    this.cleanupFn = _pre_.ipcOn(toolbarTopic.buttonClick, ipcListener)

    this.isListening = true
  }

  /**
   * 重置所有监听器并注册新的配置
   * @param config - 工具栏配置（包含回调函数）
   * @returns 处理后的工具栏配置（不含回调函数）
   */
  resetAndRegister(config: ToolbarConfigWithCallback): F2.toolbar.Config {
    // 清空旧的监听器
    this.listeners.clear()

    // 确保 IPC 监听已启动
    this.startListening()

    // 处理左侧按钮
    const leftBtns = config.leftBtns?.map((btn, index) => {
      const buttonId = btn.id || `left-btn-${Date.now()}-${index}`
      this.listeners.set(buttonId, btn.onClick)

      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      const { onClick, attrs, ...btnConfig } = btn
      return {
        ...btnConfig,
        id: buttonId,
        ...attrs // 将 attrs 属性展开并合并到按钮配置中
      } as F2.toolbar.ButtonConfig
    })

    // 处理右侧按钮
    const rightBtns = config.rightBtns?.map((btn, index) => {
      const buttonId = btn.id || `right-btn-${Date.now()}-${index}`
      this.listeners.set(buttonId, btn.onClick)

      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      const { onClick, attrs, ...btnConfig } = btn
      return {
        ...btnConfig,
        ...attrs, // 将 attrs 属性展开并合并到按钮配置中
        id: buttonId
      } as F2.toolbar.ButtonConfig
    })

    return {
      icon: config.icon,
      title: config.title,
      leftBtns,
      rightBtns
    }
  }

  /**
   * 清理所有监听器
   */
  cleanup() {
    this.listeners.clear()
    if (this.isListening && this.cleanupFn) {
      // 调用清理函数移除 IPC 监听器
      this.cleanupFn()
      this.cleanupFn = null
      this.isListening = false
    }
  }
}

// 创建全局单例
const toolbarButtonManager = new ToolbarButtonManager()

/**
 * 设置工具栏配置
 * 每次调用会重置所有按钮监听器，避免累加
 * @param config - 工具栏配置（包含回调函数）
 * @param webContentsId - 可选的 webContentsId
 */
export function setToolbarConfig(config: ToolbarConfigWithCallback, webContentsId?: number) {
  // 重置并注册新的配置
  const processedConfig = toolbarButtonManager.resetAndRegister(config)

  // 发送到主进程
  _pre_.tab.setToolbarConfig(processedConfig, webContentsId)
}

/**
 * 清理工具栏按钮监听器
 */
export function cleanupToolbarListeners() {
  toolbarButtonManager.cleanup()
}
